#include "stdafx.h"
#include "AnimatedComponent.h"

#include "SpriteSheet.h"
#include "SpriteSheetAnimation.h"
#include "SDLTexture.h"

#include "Entity.h"

using namespace std;

namespace ZeEngine
{
	s64	AnimatedComponent::m_type = -1;
	s64	AnimatedComponent::m_index = -1;

    AnimatedComponent::AnimatedComponent(SpriteSheet* pSpriteSheet) : IRenderableComponent("AnimatedComponent", m_type, m_index), m_pSpriteSheet(pSpriteSheet), 
        m_currentFrame(0), m_deltaTimeMS(0), m_pCurrentAnimation(NULL), m_frameIncrement(0)
    {
    }

    AnimatedComponent::~AnimatedComponent()
    {
    }

    void AnimatedComponent::Reset()
    {
        m_currentFrame = 0;
        m_deltaTimeMS = 0;
        m_frameIncrement = 0;
        m_pCurrentAnimation = NULL;
    }

   void AnimatedComponent::Update(u32 deltaMS)
   {
        if (m_pCurrentAnimation)
        {
            const s32 frameDuration = m_pCurrentAnimation->GetFrameDuration(m_currentFrame);
            const u32 numFrames = m_pCurrentAnimation->GetNumFrames();
            const bool reverse = m_pCurrentAnimation->IsReversable();

            //Our frame time expired move to the next frame
            if (m_deltaTimeMS >= frameDuration)
            {
                m_deltaTimeMS = 0;
                m_currentFrame += m_frameIncrement;

                //Going forward
                if (m_frameIncrement == 1)
                {
                    //We reached the end
                    if (m_currentFrame == numFrames)
                    {
                        if (reverse)
                        {
                            m_frameIncrement = -1;
                            m_currentFrame = numFrames - 1;
                        }
                        else
                        {
                            m_currentFrame = 0;
                        }
                    }
                }
                //Going backward
                else if (m_frameIncrement == -1)
                {
                    //We reached the beginning
                    if (m_currentFrame == -1)
                    {
                        m_frameIncrement = 1;
                        m_currentFrame = 0;
                    }
                }
            }

            m_deltaTimeMS += deltaMS;         
        }
   }

   void AnimatedComponent::SetCurrentAnimation(const std::string& strAnimation)
   {
       if (m_pSpriteSheet)
       {
           if (m_currentAnimation != strAnimation)
           {
               m_currentAnimation = strAnimation;
               m_deltaTimeMS = 0;
               m_currentFrame = 0;
               m_frameIncrement = 1;
               m_pCurrentAnimation = m_pSpriteSheet->GetAnimation(strAnimation);
           }
        }
   }

    const SDL_Rect AnimatedComponent::GetFrameBoundary() const
    {
        SDL_Rect boundaries = { 0, 0, 0, 0 };

        if (m_pCurrentAnimation)
        {
            boundaries = m_pCurrentAnimation->GetFrameBoundary(m_currentFrame);
        }
        else
        {
            auto pEntity = GetParent();
            stringstream ss;
            ss << "No animation set for " << pEntity->GetName();
            LOG_ERROR(ss.str());
        }

        return boundaries;
    }

    SDLTexture* AnimatedComponent::GetTexture() const
    {
        SDLTexture* pTexture = NULL;

        if (m_pSpriteSheet)
        {
            pTexture = m_pSpriteSheet->GetTexture();
        }

        return pTexture;
    }

	void AnimatedComponent::Render(SDL_Renderer& renderer, const Vector2D<float> position, const f32 rotation, f32 interpolation)
	{
		SDLTexture* pSDLTexture = GetTexture();

		if (pSDLTexture)
		{
			SDL_Texture* pTexture = pSDLTexture->GetTexture();

			SDL_Rect dest = GetFrameBoundary();
			dest.x = static_cast<int>(position.GetX());
			dest.y = static_cast<int>(position.GetY());

			if (pTexture)
			{
				//const s32 flipX = sprite.GetFlip().GetX() ? SDL_FLIP_HORIZONTAL : SDL_FLIP_NONE;
				//const s32 flipY = sprite.GetFlip().GetY() ? SDL_FLIP_VERTICAL : SDL_FLIP_NONE;
				const s32 flipX = SDL_FLIP_NONE;
				const s32 flipY = SDL_FLIP_NONE;
				SDL_RenderCopyEx(&renderer, pTexture, &GetFrameBoundary(), &dest, rotation, NULL, static_cast<SDL_RendererFlip>(flipX | flipY));
			}
		}
	}
}
